今天會完成 user_bp
,也就是要完成看貼文跟留言的部分。
首先來看看可以看到全部人貼文的 /posts
,他非常簡單,所以就不分別了,直接把 HTML 和路徑都放出來。他沒有資料庫的部分,因為我們會直接用之前的 get_posts
。
posts.html
{% extends "base.html" %}
{% block title %}Posts{% endblock %}
{% block content %}
<div>
{% for post in posts %}
<div>
{{ post['author_id'] }}
<a href="/post/{{ post['id'] }}">{{ post['title'] }}</a>
{{ post['description'] }}
{{ post['time'] }}
</div>
{% endfor %}
</div>
{% endblock %}
views.py
@user_bp.route("/posts", methods=["GET"])
@login_required
def all_posts_page():
posts = get_posts()
return render_template("posts.html", posts=posts)
基本上它的 HTML 跟 dashboard 是一樣的,只是刪掉了編輯和刪除的連結,也移掉了篩選器的表單。
路徑的部分就更簡單了,就如同剛剛所說的用 get_posts
,然後不帶任何篩選器直接抓全部,再丟到 HTML 處理,而處理方式就跟昨天 dashboard 一模一樣。
接下來我們先看看使用者底下的貼文,基本上跟剛剛一樣,但要稍微改一下資料庫,HTML 也是用一樣的,路徑改一點點就好。
helper.py
def get_user_by_username(username):
user = Users.query.filter_by(username=username).first()
return render_user_data(user.id)
views.py
@user_bp.route("/@<username>/posts", methods=["GET"])
@login_required
def user_posts_page(username):
user = get_user_by_username(username)
posts = get_posts(user["id"])
return render_template("posts.html", posts=posts)
基本上就是用使用者名稱把他整個物件都撈出來,然後當成 get_posts
的篩選器。
接下來看看瀏覽貼文的介紹,我們這次真的要從資料庫開始寫起。
def add_comment(user_id, post_id, content):
comment = Comments(user_id, post_id, content)
db.session.add(comment)
db.session.commit()
def get_comments(post_id):
comments = Comments.query.filter_by(post_id=post_id).all()
return [
{
"id": comment.id,
"author_id": comment.author_id,
"post_id": comment.post_id,
"content": comment.content,
}
for comment in comments
]
我們需要新增留言和得到留言,但我們這次就不多驗證了,抓留言的部分要轉成 dict。
接下來輪到 HTML,在這裏面需要放蠻多東西的。
post.html
{% extends "base.html" %}
{% block title %}{{ post['title'] }}{% endblock %}
{% block content %}
<form action="/post/{{ post['id'] }}" method="post">
{{ form.csrf_token }}
{{ form.content }}
{{ form.submit }}
</form>
<div>
<div>
<div>{{ post['author_id'] }}</div>
<div>{{ post['title'] }}</div>
<div>{{ post['description'] }}</div>
<div>{{ post['time'] }}</div>
<div>
{{ post['content'] | markdown }}
</div>
</div>
</div>
<div>
{% for comment in comments %}
{{ comment['author_id'] }}
{{ comment['content'] }}
{% endfor %}
</div>
{% endblock %}
裡面有一個表單,就是之前寫的新增留言的表單,接下來放的是貼文內容,比較特別的是我們終於用到 | markdown
了,這是 Flask-Markdown 的功勞,最後我們放了一堆 comments,就是從剛剛 get_comments
拿到的。
最後我們來到路徑本身。
@user_bp.route("/post/<int:post_id>", methods=["GET", "POST"])
@login_required
def view_post_page(post_id):
form = AddCommentForm()
if request.method == "GET":
post = render_post(post_id)
comments = get_comments(post_id)
return render_template("post.html", post=post, comments=comments, form=form)
if request.method == "POST":
if form.validate_on_submit():
add_comment(current_user.id, post_id, form.content.data)
flash("Comment added.")
else:
for _, errors in form.errors.items():
for error in errors:
flash(error, category="alert")
return redirect(url_for("user.view_post_page", post_id=post_id))
基本上就是類似的程式碼,但這次貼文跟留言都要抓到。
在最後,我們來到了留言的 dashboard。
def get_user_comments(user_id):
comments = Comments.query.filter_by(author_id=user_id).all()
return [
{
"id": comment.id,
"author_id": comment.author_id,
"post_id": comment.post_id,
"content": comment.content,
}
for comment in comments
]
他非常明顯跟剛剛的 get_comments
很接近,幾乎是複製貼上,只是改成了 author_id
。
接下來是 HTML 的部分。
comments.html
{% extends "base.html" %}
{% block title %}comments{% endblock %}
{% block content %}
<div>
{% for comment in comments %}
{{ comment['author_id'] }}
{{ comment['post_id'] }}
{{ comment['content'] }}
{% endfor %}
</div>
{% endblock %}
基本上他跟剛剛最下面差不多,只是加上了 comment['post_id']
,也可以在這邊加個連結連到那則貼文去。
@user_bp.route("/comments", methods=["GET"])
@login_required
def comments_dashboard_page():
comments = get_user_comments(current_user.id)
return render_template("comments.html", comments=comments)
最後來到路徑的部分,非常簡單,就是把留言抓出來然後丟給 HTML 處理好,就結束了。